(function (window) {
	'use strict';
	// Your starting point. Enjoy the ride!

	// 创建一个指针，用于本地持久化标志
	const TODOS_KEY = 'todos-vue'
	// 创建一个对象，内部使用localStorage的getItem（数据读取）和setItem（数据写入）方法
	let todoStorage = {
		get() {
			// 返回数据，我们需要js代码数据，需要使用JSON.parse转换一下
			// 使用[]用于备用，如果现在没有数据使用空数组
			return JSON.parse(localStorage.getItem(TODOS_KEY)) || []
		},
		set(todos) {
			// 调用setItem方法
			// 参数1:指针名字
			// 参数2:数据，这里我们需要转为json数据才能存储（JSON.stringify）
			localStorage.setItem(TODOS_KEY, JSON.stringify(todos))
		}
	}
	// 新建Vue实例
	new Vue({
		// 挂载实例，这里使用类名挂载
		el: '.todoapp',
		// 数据
		data: {
			// 事项列表数据，内部每一个对象都是一个事项
			// todos: [{
			// 		// 事项id，用在v-for中标示数据
			// 		id: 1,
			// 		// 事项内容
			// 		content: '内容1',
			// 		// 事项是否选中
			// 		completed: true
			// 	},
			// 	{
			// 		id: 2,
			// 		content: '内容2',
			// 		completed: false
			// 	},
			// 	{
			// 		id: 3,
			// 		content: '内容3',
			// 		completed: true
			// 	}
			// ],
			// 在这里使用持久化数据，因为当前什么都没有，所以是数据
			todos: todoStorage.get(),
			// 用于动态传入底部数值统计区域的单位
			item: 'item',
			// 新增事项输入框内容
			newTodo: '',
			// 用于保存当前编辑的事项信息，用于对比
			editing: null,
			// 保存编辑的事项原始的内容，以便后期取消保存可能找到
			oldTodoContent: '',
			// 当前展示模式，默认为全部，另外还有active（未完成）、completed（已完成）
			fliter: 'all',
			// 存储不同时模式下输出的不同数据的函数
			fliterFn: {
				// all模式下直接返回全部todos
				all: (todos) => todos,
				// active模式下筛选全部completed为flase的事项
				active: (todos) => {
					return todos.filter(function (todo) {
						return !todo.completed
					})
				},
				// completed模式下筛选全部completed为true的事项，这个是上面的ES6简写
				completed: (todos) => {
					return todos.filter(todo => todo.completed)
				}
			}
		},
		// 函数
		methods: {
			// 输入框抬起键盘事件
			addNewTodo() {
				// 判断newTodo是否为空
				if (this.newTodo !== '') {
					// 如果不为空，向todos添加一条事项
					this.todos.push({
						// 为了简便，这里简单设置一个id，如果想保证id绝对不重复，可以使用时间戳
						id: this.todos.length + 1,
						// 内容就是newTodo内容
						content: this.newTodo,
						// 默认flase
						completed: false
					})
					// 清空输入框
					this.newTodo = ''
				}
			},
			// 删除单个事项按钮点击事件
			removeLi(todo) {
				// 获取点击的按钮对应的事项在todos中的下标
				const i = this.todos.indexOf(todo)
				// 调用数组的splice方法删除指定下标
				this.todos.splice(i, 1)
			},
			// 批量删除已完成事项
			clearCompleted() {
				// 过滤todos，把所有completed = true的全部去掉
				// !todo.completed全部取反，如果结果是true才能得以保留
				this.todos = this.todos.filter(todo => !todo.completed)
			},
			// 双击事项事件函数，将要编辑的事项信息保存起来，vue会自动进行处理
			dbclickLabel(item) {
				this.editing = item
				this.oldTodoContent = item.content
			},
			// 取消编辑事件函数
			cancelEditing(todo) {
				// 清除当前编辑事项信息
				this.editing = null
				// 将旧的事项内容替换回来
				todo.content = this.oldTodoContent
			},
			// 保存编辑事件函数
			saveEdit(todo) {
				// （这一步是为了后面 if (!todo.content) 作准备的）判断是否当前有编辑的事项，如果没有直接返回，因为enter事件会再次触发blur事件，导致事件触发两次，会发生两次删除，而第二次删除找不到当前编辑事项会默认删除最后一个事项，导致重复删除
				if (this.editing === null) return
				// 清除编辑事项
				this.editing = null
				// 获取我们输入的内容并去掉前后空格
				todo.content = todo.content.trim()
				// 判断内容是否为空，如果为空删除编辑的事件
				if (!todo.content) {
					this.removeLi(todo)
				}
			}
		},
		// 计算属性
		computed: {
			// 用于统计未完成项目个数
			itemLeft() {
				let num = 0
				for (const i of this.todos) {
					if (i.completed === false) {
						num++
					}
				}
				return num
			},
			// 用于控制多选按钮多选效果
			toggleAll: {
				// 根据itemLeft判断是否全部事项都完成了，都完成了返回ture
				get() {
					return this.itemLeft === 0
				},
				// 用于多选按钮修改数据
				// 因为toggleAll绑定了按钮的value，所以当我们点击按钮的时候按钮会变化，从而传回这里
				set(value) {
					// value为传回的数值，我们在这里把所有事项的completed修改为value即可
					for (const i of this.todos) {
						i.completed = value
					}
				}
			},
			// 用于输出上面fliterFn不同函数的结果
			returnTodos() {
				// 读取fliter模式，调取fliterFn对象相应方法，然后返回结果
				return this.fliterFn[this.fliter](this.todos)
			}
		},
		// 自定义指令
		directives: {
			// 编辑状态下输入框自动获取焦点
			'autofocus'(el, binding) {
				// 判断自定义事项条件是否成立
				if (binding.value) {
					// 如果成立，编辑事项的输入框获得焦点
					el.focus();
				}
			}
		},
		// 监听器
		watch: {
			// 侦听todos数据，一旦变化就跟新持久化数据
			todos: {
				// 监听对象内部变化
				deep: true,
				// 可简写为handler：todoStorage.set
				// 把调用set方法更改数据
				handler(value) {
					todoStorage.set(value)
				}
			}
		}
	})
})(window);
